package de.uni.bremen.estudent.lbs.tasks;


import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.util.Log;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.XStreamException;

import de.uni.bremen.estudent.lbs.models.Meal;
import de.uni.bremen.estudent.lbs.models.Menu;
import de.uni.bremen.estudent.lbs.provider.EstudentLBSContract.Meals;
import de.uni.bremen.estudent.lbs.util.Constants;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Calendar;


/**
 * This thread tries to get the mensa-menu of a week from food supplier and save
 * it in the database.
 * 
 * @author bahlfeld
 */
public final class GetFoodAsyncTask extends AsyncTask<Void, Void, Void> {

    /**
     * URL where you can geht the gw2-menu as xml.
     */
    private static String gw2Url = "http://17.foodspl.appspot.com/mensa?id=gw2";

    /**
     * URL where you can get the mensa-menu as xml.
     */
    private static String mensaUrl = "http://17.foodspl.appspot.com/mensa?id=uni";
    /**
     * Tag to identify this class.
     */
    private static final String TAG = "eStudentLBS - GetFoodAsyncTask";

    /**
     * Context object.
     */
    private final Context mContext;

    /**
     * Callendar object. to get the current weeknumber.
     */
    private final Calendar mCurrentDate;

    /**
     * Constructor for the asynctask.
     * 
     * @param context Context object.
     */
    public GetFoodAsyncTask(final Context context) {
        mContext = context;
        mCurrentDate = Calendar.getInstance();
    }

    /*
     * (non-Javadoc)
     * 
     * @see android.os.AsyncTask#doInBackground(Params[])
     */
    @Override
    protected Void doInBackground(final Void... params) {
        // TODO: Read sharedpreferences...check last mensa update.

        if (mContext == null) {
            return null;
        }
        SharedPreferences prefs = mContext
                                        .getSharedPreferences(Constants.PREFS_NAME,
                                                              0);

        if (prefs == null) {
            return null;
        } // check if key exists. if
        if (prefs.contains(Constants.LAST_MENSA_UPDATE)) {
            // Check if update is needed
            if (mCurrentDate.get(Calendar.WEEK_OF_YEAR) == prefs
                                            .getInt(Constants.LAST_MENSA_UPDATE,
                                                    0)) {
                // updated allready this week.

                return null;
            }
        }

        deleteExistingMensaData();
        // Update mensa meals
        Menu menu = parseURL(mensaUrl);
        insertMenuData(menu, Constants.MENSA_ID);
        menu = parseURL(gw2Url);
        insertMenuData(menu, Constants.GW2_ID);
        SharedPreferences.Editor editor = prefs.edit();
        editor.putInt(Constants.LAST_MENSA_UPDATE,
                      mCurrentDate.get(Calendar.WEEK_OF_YEAR));
        editor.commit();

        return null;
    }

    private ContentValues buildItem(Meal food, int day, int mensaId) {
        ContentValues item = new ContentValues();
        item.put(Meals.MEAL_NAME, food.getName());
        item.put(Meals.MEAL_DESC, food.getDesc());
        item.put(Meals.MEAL_EXTRA, food.getExtra());
        item.put(Meals.MEAL_STAFF_PRICE, food.getStaffprice());
        item.put(Meals.MEAL_STUDENT_PRICE, food.getStudentprice());
        item.put(Meals.MEAL_WEEK_DAY, day);
        item.put(Meals.MEAL_PLACE, mensaId);
        return item;
    }

    /**
     * Delets the existing meals. If any exists.
     */
    private void deleteExistingMensaData() {
        ContentResolver cr = mContext.getContentResolver();
        cr.delete(Meals.CONTENT_URI, null, null);
    }

    /**
     * Inserts the new meals into the meals db.
     * 
     * @param menu Which contains the new meals data.
     */
    private void insertMenuData(final Menu menu, int mensaId) {
        if (menu == null) {
            return;
        }
        final ContentResolver cr = mContext.getContentResolver();
        for (Meal food : menu.getMon()) {
            cr.insert(Meals.CONTENT_URI, buildItem(food, 1, mensaId));
        }
        for (Meal food : menu.getTue()) {
            cr.insert(Meals.CONTENT_URI, buildItem(food, 2, mensaId));
        }
        for (Meal food : menu.getWes()) {
            cr.insert(Meals.CONTENT_URI, buildItem(food, 3, mensaId));
        }
        for (Meal food : menu.getThu()) {
            cr.insert(Meals.CONTENT_URI, buildItem(food, 4, mensaId));
        }
        for (Meal food : menu.getFri()) {
            cr.insert(Meals.CONTENT_URI, buildItem(food, 5, mensaId));
        }
    }

    private Menu parseURL(String url) {
        // Update...
        XStream xstream = new XStream();
        xstream.processAnnotations(Meal.class);
        xstream.processAnnotations(Menu.class);
        Menu menu = new Menu();

        try {
            URL url2Meal = new URL(url);
            BufferedReader bfReader = new BufferedReader(new InputStreamReader(
                                            url2Meal.openStream()));
            String line;
            // Reading the content and convert it into objects.!

            while ((line = bfReader.readLine()) != null) {
                menu = (Menu) xstream.fromXML(line);
            }
        } catch (XStreamException e1) {
            Log.e(TAG, e1.getMessage());
        } catch (MalformedURLException e2) {
            e2.printStackTrace();
        } catch (IOException e3) {
            e3.printStackTrace();
        }

        return menu;
    }
}
